﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading.Tasks;
using System.Linq;

namespace Model
{
    [ObjectEvent]
    public class AppManagerComponentEvent : ObjectEvent<AppManagerComponent>, IStart
    {
        public void Start()
        {
            this.Get().Start();
        }
    }

    public class AppManagerComponent : Component
    {
        private readonly Dictionary<int, Process> processes = new Dictionary<int, Process>();

        public void Start()
        {
            StartConfig[] startConfigs = Game.Scene.GetComponent<StartConfigComponent>().GetAll();

            foreach (StartConfig item in startConfigs)
            {
                if (item.AppType.Is(AppType.Manager) || !item.IsRun)
                    continue;
                StartProcess(item.AppId);
            }

            this.WatchProcessAsync();
        }

        public void StartProcess(int appId)
        {
            OptionComponent optionComponent = Game.Scene.GetComponent<OptionComponent>();
            StartConfigComponent startConfigComponent = Game.Scene.GetComponent<StartConfigComponent>();
            string configFile = optionComponent.Options.Config;
            StartConfig startConfig = startConfigComponent.Get(appId);

            const string exe = @"dotnet";
            string arguments = $@"{AppDomain.CurrentDomain.BaseDirectory}\App.dll --appId={startConfig.AppId} --appType={startConfig.AppType} --config={configFile}";
            Log.Info($"{exe} {arguments}");

            try
            {
                ProcessStartInfo info = new ProcessStartInfo { FileName = exe, Arguments = arguments, CreateNoWindow = false,UseShellExecute=true };
                Process process = Process.Start(info);
                this.processes.Add(startConfig.AppId, process);
            }
            catch (Exception e)
            {
                Log.Error(e.ToString());
            }
        }

        /// <summary>
        /// 监控启动进程，如果启动进程挂了重新拉起。
        /// </summary>
        public async void WatchProcessAsync()
        {
            while (true)
            {
                // 等待5秒
                await Task.Delay(5000);

                if (this.Id == 0)
                    return;

                foreach (int  appId in this.processes.Keys.ToArray())
                {
                    Process process = this.processes[appId];
                    if (!process.HasExited)
                        continue;

                    this.processes.Remove(appId);
                    process.Dispose();

                    StartProcess(appId);
                }

            }
        }
    }
}
